package odmd.handler;

import java.io.IOException;
import java.nio.ByteBuffer;

import odmd.Constants;

/**
 * 
 * @author <a mailto="hwangsyin@gmail.com">King</a>
 *
 */
public final class Response {
	private byte magic = Constants.PROTOCOL_TYPE_RESPONSE;
	private byte opcode = -1;
	private int status = -1;
	private int keyLength;
	private long bodyLength;
	private String key;
	private String value;
	public ByteBuffer getResponseBuffer() {
		int keyLength = 0;
		long valueLength = 0L;
		byte[] keyBytes = null;
		byte[] valueBytes = null;
		try {
			if(key != null) {
				keyBytes = key.getBytes(Constants.PROTOCOL_CHARSET);
				keyLength = keyBytes.length;
			}
			if(value != null) {
				valueBytes = value.getBytes(Constants.PROTOCOL_CHARSET);
				valueLength = valueBytes.length;
			}
		} catch(IOException e) {
			e.printStackTrace();
		}
		
		ByteBuffer buff = ByteBuffer.allocate(Constants.PROTOCOL_HEADER_LENGTH + keyLength + (int)valueLength);
		buff.put(0, magic);
		buff.put(1, opcode);
		buff.putInt(2, status);
		buff.putInt(20, keyLength);
		buff.putLong(24, keyLength + valueLength);
		
		buff.position(Constants.PROTOCOL_HEADER_LENGTH);
		if(keyBytes != null) {
			buff.put(keyBytes);
		}
		if(valueBytes != null) {
			buff.put(valueBytes);
		}
		
		buff.flip();
		return buff;
	}
	public byte getMagic() {
		return magic;
	}
	public void setMagic(byte magic) {
		this.magic = magic;
	}
	public byte getOpcode() {
		return opcode;
	}
	public void setOpcode(byte opcode) {
		this.opcode = opcode;
	}
	public int getStatus() {
		return status;
	}
	public void setStatus(int status) {
		this.status = status;
	}
	public String getKey() {
		return key;
	}
	public void setKey(String key) {
		this.key = key;
	}
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	public static Response parse(ByteBuffer buff) {
		Response resp = null;
		
		if(buff != null) {
			resp = new Response();
			
			resp.setMagic(buff.get(0));
			resp.setOpcode(buff.get(1));
			resp.setStatus(buff.get(2));
			resp.setKeyLength(buff.getInt(20));
			resp.setBodyLength(buff.getLong(24));
		}
		
		return resp;
	}
	public int getKeyLength() {
		return keyLength;
	}
	public void setKeyLength(int keyLength) {
		this.keyLength = keyLength;
	}
	public long getBodyLength() {
		return bodyLength;
	}
	public void setBodyLength(long bodyLength) {
		this.bodyLength = bodyLength;
	}
	public long getValueLength() {
		return this.bodyLength - this.keyLength;
	}
	//GET operation response header
	public static void get(ByteBuffer buff, int responseCode, int keyLength, long totalBodyLength) {
		buff.put(0, Constants.PROTOCOL_TYPE_RESPONSE);
		buff.put(1, Constants.PROTOCOL_OPCODE_GET);
		buff.putInt(2, responseCode);
		for(int i = 6; i < 20; i++) {
			buff.put(i, (byte)0);
		}
		buff.putInt(20, keyLength);
		buff.putLong(24, totalBodyLength);
	}
	//LIST operation response header
	public static void list(ByteBuffer buff, int responseCode, int keyLength, long totalBodyLength) {
		buff.put(0, Constants.PROTOCOL_TYPE_RESPONSE);
		buff.put(1, Constants.PROTOCOL_OPCODE_LIST);
		buff.putInt(2, responseCode);
		for(int i = 6; i < 20; i++) {
			buff.put(i, (byte)0);
		}
		buff.putInt(20, keyLength);
		buff.putLong(24, totalBodyLength);
	}
}
